#include "Infrared.h"


#pragma romdata

/** @brief lookup_IR
  @param address - address in the lookup talbe
 @return distance - distance in mm to the object
 @detail Lookup table for infrared sensor
 @todo nothing, I hope
 @author Gennady Bolotov
**/

const rom unsigned int lookup_IR[]={
	0x0573,
	0x053F,
	0x0514,
	0x04EC,
	0x04C5,
	0x04A1,
	0x047E,
	0x045E,
	0x043F,
	0x0424,
	0x040A,
	0x03F3,
	0x03DF,
	0x03CC,
	0x03BA,
	0x03AA,
	0x039B,
	0x038E,
	0x0381,
	0x0375,
	0x0369,
	0x035F,
	0x0355,
	0x034B,
	0x0342,
	0x0339,
	0x0330,
	0x0328,
	0x0321,
	0x0319,
	0x0312,
	0x030B,
	0x0304,
	0x02FE,
	0x02F8,
	0x02F2,
	0x02EC,
	0x02E6,
	0x02E0,
	0x02DB,
	0x02D5,
	0x02D0,
	0x02CB,
	0x02C6,
	0x02C1,
	0x02BD,
	0x02B8,
	0x02B3,
	0x02AF,
	0x02AB,
	0x02A6,
	0x02A2,
	0x029E,
	0x029A,
	0x0296,
	0x0293,
	0x0294,
	0x0295,
	0x028E,
	0x028A,
	0x0287,
	0x0283,
	0x027F,
	0x027C,
	0x0279,
	0x0276,
	0x0271,
	0x026E,
	0x026B,
	0x0268,
	0x0264,
	0x0261,
	0x025E,
	0x025C,
	0x025D,
	0x0258,
	0x0255,
	0x0252,
	0x024F,
	0x024C,
	0x0249,
	0x0246,
	0x0243,
	0x0241,
	0x023E,
	0x023B,
	0x0238,
	0x0236,
	0x0233,
	0x0231,
	0x022E,
	0x022B,
	0x0229,
	0x0226,
	0x0224,
	0x0221,
	0x021F,
	0x021E,
	0x021A,
	0x0218,
	0x0215,
	0x0213,
	0x0211,
	0x020E,
	0x020C,
	0x020A,
	0x0208,
	0x0205,
	0x0203,
	0x0201,
	0x01FF,
	0x01FD,
	0x01FB,
	0x01F9,
	0x01F6,
	0x01F4,
	0x01F2,
	0x01F0,
	0x01EE,
	0x01EC,
	0x01EA,
	0x01E8,
	0x01E6,
	0x01E4,
	0x01E2,
	0x01E0,
	0x01DE,
	0x01DC,
	0x01DB,
	0x01D9,
	0x01D7,
	0x01D5,
	0x01D3,
	0x01D1,
	0x01CF,
	0x01CE,
	0x01CC,
	0x01CA,
	0x01C8,
	0x01C6,
	0x01C5,
	0x01C3,
	0x01C1,
	0x01BF,
	0x01BE,
	0x01BC,
	0x01BA,
	0x01B9,
	0x01B7,
	0x01B5,
	0x01B4,
	0x01B2,
	0x01B0,
	0x01AF,
	0x01AD,
	0x01AB,
	0x01AA,
	0x01A8,
	0x01A7,
	0x01A5,
	0x01A4,
	0x01A2,
	0x01A0,
	0x019F,
	0x019D,
	0x019C,
	0x019A,
	0x0199,
	0x0197,
	0x0196,
	0x0194,
	0x0193,
	0x0191,
	0x0190,
	0x018E,
	0x018D,
	0x018B,
	0x018A,
	0x0188,
	0x0187,
	0x0186,
	0x0184,
	0x0183,
	0x0181,
	0x0180,
	0x017F,
	0x017D,
	0x017C,
	0x017A,
	0x017B,
	0x0179,
	0x0178,
	0x0176,
	0x0175,
	0x0174,
	0x0172,
	0x0171,
	0x0170,
	0x016E,
	0x016D,
	0x016C,
	0x016A,
	0x016B,
	0x0169,
	0x0168,
	0x0166,
	0x0167,
	0x0165,
	0x0164,
	0x0163,
	0x0161,
	0x0162,
	0x0160,
	0x015F,
	0x015D,
	0x015E,
	0x015C,
	0x015B,
	0x015A,
	0x0158,
	0x0159,
	0x0157,
	0x0156,
	0x0155,
	0x0154,
	0x0152,
	0x0153,
	0x0151,
	0x0150,
	0x014F,
	0x014E,
	0x014C,
	0x014B,
	0x014A,
	0x0149,
	0x0148,
	0x0146,
	0x0147,
	0x0145,
	0x0144,
	0x0143,
	0x0142,
	0x0141,
	0x013F,
	0x013E,
	0x013D,
	0x013C,
	0x013B,
	0x013A,
	0x0139,
	0x0137,
	0x0136,
	0x0135,
	0x0134,
	0x0133,
	0x0132,
	0x0131,
	0x0130,
	0x012F,
	0x012E,
	0x012C,
	0x012B,
	0x012A,
	0x0129,
	0x0128,
	0x0127,
	0x0126,
	0x0125,
	0x0124,
	0x0123,
	0x0122,
	0x0121,
	0x0120,
	0x011F,
	0x011E,
	0x011C,
	0x011B,
	0x011A,
	0x0119,
	0x0118,
	0x0117,
	0x0116,
	0x0115,
	0x0114,
	0x0113,
	0x0112,
	0x0111,
	0x0110,
	0x010F,
	0x010E,
	0x010D,
	0x010C,
	0x010B,
	0x010A,
	0x0109,
	0x0108,
	0x0107,
	0x0106,
	0x0105,
	0x0104,
	0x0103,
	0x0102,
	0x0101,
	0x0100,
	0x00FF,
	0x00FE,
	0x00FD,
	0x00FC,
	0x00FB,
	0x00FA,
	0x00F9,
	0x00F8,
	0x00F7,
	0x00F6,
	0x00F5,
	0x00F4,
	0x00F3,
	0x00F2,
	0x00F1,
	0x00F0,
	0x00EF,
	0x00EE,
	0x00ED,
	0x00EC,
	0x00EB,
	0x00EA,
	0x00E9,
	0x00E8,
	0x00E7,
	0x00E6,
	0x00E5,
	0x00E4,
	0x00E3,
	0x00E2,
	0x00E1,
	0x00E0,
	0x00DF,
	0x00DE,
	0x00DD,
	0x00DC,
	0x00DB,
	0x00DA,
	0x00D9,
	0x00D8,
	0x00D7,
	0x00D6,
	0x00D5,
	0x00D4,
	0x00D3,
	0x00D2,
	0x00D1,
	0x00D0,
	0x00CF,
	0x00CE,
	0x00CD,
	0x00CC,
	0x00CB,
	0x00CA,
	0x00C9,
	0x00C8};



#pragma code 


unsigned int buffer_IR[BUFFSIZE_IR]={0};		/*buffer to store ADC readings*/

/********************************************************
/* FUNCTIONS */

/**
* @brief setup_IR
* @param none
* @return none
* @detail function used to set-up ADC and UART hardware
* to test Infrared Sensor
*/

void setup_IR(void)
{
	/*set up transmitter*/

//	TXSTA|=0b00000100;	/*set the fast trans (BRGH)*/
//	SPBRG=SPBRGSET;
//	TXSTA&=0b11101111;	/*clear SYNC*/
//	RCSTA|=0b10000000;	/*set SPEN*/
//	TXSTA|=0b00100000;	/*set TXEN*/
	
	/*set up ADC*/

	TRISA|=0b00000010;			/*set pin RA1 as input*/
	OpenADC(ADC_FOSC_2			/*clock source/2*/
			&ADC_RIGHT_JUST		/*right justification*/ 
			&ADC_5ANA_0REF,		/*voltage level between 0-5V*/
			ADC_CH1				/*input channel 1*/
			&ADC_INT_OFF		/*interrupt OFF*/
			);
}
unsigned int getADC(void)		/*function to read ADC*/
{
	unsigned int result=NULL;
	
	ConvertADC();		/*start the conversion*/
	while(BusyADC());	/*wait until conversion is complete*/
	result=ReadADC();	/*get the result*/
	
	return	result;		/*return*/
}

/** 
* @brief fill_IR_buffer 
* @param none
* @return none
* @details The function fills up the Infrared dedicated buffer with values from ADC.
* @note The buffer is a global array buffer_IR[]. The size of the buffer is defined 
* by a gloabal variable BUFFSIZE_IR.
* @todo nothing, I hope
* @author Gennady Bolotov
*/

void fill_IR_buffer(void)
{
	unsigned int i=NULL;	/*counter variable*/
	
	for(i=0;i<BUFFSIZE_IR;i++)
	{							/*read values from ADC*/
		buffer_IR[i]=getADC(); /*and write them into buffer*/
	}
}

unsigned int find_mean(void)
{
	unsigned int i=NULL;	/*counter*/
	unsigned int sum=0;
	unsigned int mean=0;

	for(i=0;i<BUFFSIZE_IR;i++)	/*sum-up all the values*/
	{
		sum+=buffer_IR[i];
	}

	mean=sum/i;				/*get average*/
	
	return mean;
}

/** 
* @brief get_IR 
* @param none
* @return voltage - average voltage value from IR sensor
* @details The function fills up the Infrared dedicated buffer with values from ADC and 
* then calculates and returns their mean value.
* @note buffer and its size are determined by global variabled buffer_IR[] and BUFFSIZE_IR
* respectively.
* @todo nothing, I hope
* @author Gennady Bolotov
*/

unsigned int get_IR(void)
{
	unsigned int result=NULL;
	
	fill_IR_buffer();
	result=find_mean();
	return result;
}


/**
* @brief send_in
* @param data - data to be sent.
* @return none
* @details The function takes an integer value 'data', converts it into hex ASCII equivalent
* and sends it via UART to hyperterminal.
* @note Serial Transmitter must be configured before calling this function.
* @todo need to find a way to convert hex into decimal ASCII representation.
* @author Gennady Bolotov
*/



/**
 @brief fetch_IR_dist
 @param address - address in the lookup table
 @return distance - distance in mm, read from lookup table
 @details The function reads the voltage read from IR sensor and converts it
 into equivalent address in the lookup table. It then takes the value stored in
 this address and returns the distance to object in mm.
 @note All values are in hex.
 @todo nothing, I hope
 @author Gennady Bolotov
**/

unsigned int fetch_IR_dist(unsigned int address)
{
	unsigned int result=NULL;

	/*make sure the address is within the range*/

	if (address>0x01ED) /*if it's above max value*/
	{
		address=0x01ED; /*convert it to max value*/
	}
	if (address<0x08A) /*if it's below min value*/
	{
		address=0x08A; /*convert it to min value*/
	}

	memcpypgm2ram(&result, (&lookup_IR[(address-0x08A)]),2); /*read the lookup table 
															 (address is offset by 0x8A)*/
	return result; /*return*/
}

/*void main(void)
{
	unsigned int average=NULL;
	unsigned int distance=NULL;
	
	setup_IR();
	while(1)
	{
		fill_IR_buffer();
		average=find_mean();
		
		distance=fetch_IR_dist(average);
		send_int(distance);
	}
}*/
		